﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.IO;
using System.Diagnostics;

namespace ExeInvoker
{
    class ProgramInfoViewModelManager
    {
        private static readonly ProgramInfoViewModelManager instance = new ProgramInfoViewModelManager();
        private static readonly string filePath = System.IO.Path.Combine(new FileInfo(typeof(ProgramInfoViewModelManager).Assembly.Location).DirectoryName, "Programs.xml");

        public static ProgramInfoViewModelManager Instance { get { return instance; } }

        private List<ProgramInfoViewModel> items = new List<ProgramInfoViewModel>();

        public ProgramInfoViewModel[] AllProgramInfoViewModels { get { return this.items.ToArray(); } }

        public void Load()
        {
            if (File.Exists(filePath) == false)
            {
                return;
            }
            XDocument xDoc = XDocument.Load(filePath);
            foreach (XElement xe in xDoc.Root.Elements())
            {
                ProgramInfoViewModel m = new ProgramInfoViewModel();
                m.ProgramPath = (xe.Element("ProgramPath").FirstNode as XCData).Value;
                m.ProgramArgs = (xe.Element("ProgramArgs").FirstNode as XCData).Value;
                m.StrokeKeys = (xe.Element("StrokeKeys").FirstNode as XCData).Value;
                this.items.Add(m);
            }
        }

        public void Save()
        {
            XDocument xdoc = XDocument.Parse("<Programs/>");
            foreach (var item in this.items)
            {
                XElement xpro = new XElement("Program");
                XElement xpath = new XElement("ProgramPath", new XCData(item.ProgramPath));
                XElement xargs = new XElement("ProgramArgs", new XCData(item.ProgramArgs));
                XElement xkeys = new XElement("StrokeKeys", new XCData(item.StrokeKeys));

                xpro.Add(xpath);
                xpro.Add(xargs);
                xpro.Add(xkeys);

                xdoc.Root.Add(xpro);
            }
            if (File.Exists(filePath))
            {
                File.Delete(filePath);
            }
            xdoc.Save(filePath);
        }

        public void Add(ProgramInfoViewModel item)
        {
            this.items.Add(item);
        }

        public void Remove(ProgramInfoViewModel item)
        {
            this.items.Remove(item);
        }

        public string Execute(ProgramInfoViewModel item)
        {
            try
            {
                StringBuilder output = new StringBuilder();
                ProcessStartInfo psi = new ProcessStartInfo(item.ProgramPath, item.ProgramArgs);
                psi.CreateNoWindow = true;
                psi.RedirectStandardError = true;
                psi.RedirectStandardInput = true;
                psi.RedirectStandardOutput = true;
                psi.UseShellExecute = false;
                psi.ErrorDialog = true;
                psi.WorkingDirectory = "C:\\";
                Process p = Process.Start(psi);

                if (item.ProgramPath.Equals("CMD", StringComparison.OrdinalIgnoreCase) || item.ProgramPath.Equals("CMD.EXE", StringComparison.OrdinalIgnoreCase))
                {
                    p.StandardInput.WriteLine(item.ProgramArgs);
                    p.StandardInput.WriteLine("exit");
                }
                p.WaitForExit();
                string line = null;
                while ((line = p.StandardOutput.ReadLine()) != null)
                {
                    output.AppendLine(line);
                }
                return output.ToString();
            }
            catch (Exception ex)
            {
                return ex.Message + Environment.NewLine + ex.StackTrace;
            }
        }
    }
}
